﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace Qianke.Core.Common.Decode
{
    public class AESHelper
    {
        private byte[] _key = null;
        private byte[] _iv = null;

        private SymmetricAlgorithm _aes;

        private AESHelper()
        {

        }

        public static AESHelper Create()
        {

            var aes = new AESHelper();
            aes._aes = Aes.Create();
            aes._aes.Padding = PaddingMode.PKCS7;
            aes._aes.Mode = CipherMode.ECB;
            return aes;
        }

        public static AESHelper Create(SymmetricAlgorithm algorithm)
        {
            var aes = new AESHelper();
            aes._aes = algorithm;
            aes._aes.Padding = PaddingMode.PKCS7;
            aes._aes.Mode = CipherMode.ECB;
            return aes;
        }


        public static AESHelper CreateTriple()
        {
            var aes = new AESHelper();
            aes._aes = new TripleDESCryptoServiceProvider();
            aes._aes.Padding = PaddingMode.PKCS7;
            aes._aes.Mode = CipherMode.ECB;
            return aes;
        }

        #region 配置AES

        public AESHelper SetCipherMode(CipherMode mode)
        {
            _aes.Mode = mode;
            return this;
        }

        public AESHelper SetPadding(PaddingMode padding)
        {
            _aes.Padding = padding;
            return this;
        }

        public AESHelper SetKey(byte[] key)
        {
            if (key == null)
                throw new Exception("AesHelper配置异常，Key不能为空");
            if (key.Length > 32)
                this._key = key.Take(32).ToArray();
            else
                _key = key;
            return this;
        }

        public AESHelper SetIV(byte[] iv)
        {
            if (iv == null)
                throw new Exception("AesHelper配置异常，IV不能为空");
            if (iv.Length > 32)
                this._iv = iv.Take(32).ToArray();
            else
                _iv = iv;
            return this;
        }


        public AESHelper SetKeyFromString(string key, Encoding keyEncoding = null)
        {
            if (string.IsNullOrEmpty(key))
                throw new Exception("AesHelper配置异常 Key不能为空");
            keyEncoding = keyEncoding ?? Encoding.UTF8;
            return SetKey(keyEncoding.GetBytes(key));
        }


        public AESHelper SetKeyFromByteString(string byteKey)
        {
            if (string.IsNullOrEmpty(byteKey))
                throw new Exception("AesHelper配置异常 Key不能为空");
            return SetKey(BytesEncryptHelper.DecodeBytes(byteKey));
        }


        public AESHelper SetIVFromString(string iv, Encoding ivEncoding = null)
        {
            ivEncoding = ivEncoding ?? Encoding.UTF8;
            return !string.IsNullOrEmpty(iv) ? SetIV(ivEncoding.GetBytes(iv)) : this;
        }

        public AESHelper SetIVFromByteString(string byteString)
        {
            return string.IsNullOrEmpty(byteString) ? this : SetKey(BytesEncryptHelper.DecodeBytes(byteString));
        }
        #endregion

        #region 解密
        public byte[] Decrypt(byte[] buffer)
        {
            using (var ms = new MemoryStream())
            {
                using (var aesStream = new CryptoStream(ms, _aes.CreateDecryptor(_key, _iv), CryptoStreamMode.Write))
                {
                    aesStream.Write(buffer, 0, buffer.Length);
                    aesStream.FlushFinalBlock();
                    return ms.ToArray();
                }
            }
        }

        public byte[] DecryptFromString(string encodString, Encoding encoding = null)
        {
            encoding = encoding ?? Encoding.UTF8;
            return Decrypt(encoding.GetBytes(encodString));
        }

        public byte[] DecryptFromByteString(string byteString)
        {
            return Decrypt(BytesEncryptHelper.DecodeBytes(byteString));
        }

        public string DecryptStrToStr(string encodString, Encoding encoding = null)
        {
            encoding = encoding ?? Encoding.UTF8;
            var buffer = DecryptFromString(encodString);
            return encoding.GetString(buffer);
        }

        public string DecryptByteStringToString(string byteString, Encoding encoding = null)
        {
            encoding = encoding ?? Encoding.UTF8;
            byte[] buffer = DecryptFromByteString(byteString);
            return encoding.GetString(buffer);
        }

        #endregion

        #region 加密
        public byte[] Encrypt(byte[] buffer)
        {
            using (var ms = new MemoryStream())
            {
                using (var aesStream = new CryptoStream(ms, _aes.CreateEncryptor(_key, _iv), CryptoStreamMode.Write))
                {
                    aesStream.Write(buffer, 0, buffer.Length);
                    aesStream.FlushFinalBlock();
                    return ms.ToArray();
                }
            }
        }


        public byte[] EncryptFromString(string encodString, Encoding encoding = null)
        {
            encoding = encoding ?? Encoding.UTF8;
            return Encrypt(encoding.GetBytes(encodString));
        }

        public byte[] EncryptFromByteString(string byteString)
        {
            return Encrypt(BytesEncryptHelper.DecodeBytes(byteString));
        }

        public string EncrytStrToBase64Str(string encodString, Encoding encoding = null)
        {
            var buffer = EncryptFromString(encodString, encoding);
            return Convert.ToBase64String(buffer);
        }

        public string EncrytStringToByteString(string encodString, Encoding encoding = null)
        {
            var buffer = EncryptFromString(encodString, encoding);
            return BytesEncryptHelper.EncodeBytes(buffer);
        }
        #endregion
    }
}
